/*******************************************************************************
 * @file    bsp_flash.c
 * @brief   the device flash driver implementation
 *
 * @version 1.0.0
 *******************************************************************************
 * @license Refer License or other description Docs
 * @author  Felix
 ******************************************************************************/
#include "cpu/bsp_flash.h"

#define FLASH_PAGE_SIZE         0x00000200      /* 512 in byte */
#define FLASH_FREQ_MODE         6U

/* Flash driver Structure */
static bool sInitFlag = false;
/****
Global Functions
****/

bool BSP_FlashInit(void)
{
    en_result_t enResult = Error;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralFlash, TRUE);
    /* Init callback, flash cycle, sleepmode */
    enResult = Flash_Init(FLASH_FREQ_MODE, TRUE);
    if(Ok == enResult){
        sInitFlag = true;
    } else {
        sInitFlag = false;
    }

    return sInitFlag;
}

__INLINE bool BSP_CheckFlag(void)
{
    return sInitFlag;
}

bool BSP_FlashRead(uint32_t addr, uint32_t *data, uint32_t len)
{
    uint32_t index;
    if(!sInitFlag) {
        /* Flash has not Init */
        return false;
    }

    for (index = 0; index < len; index++){
        data[index] = REG_READ32(addr + index * 4);
    }

    return true;
}

bool BSP_FlashWrite(uint32_t addr, const uint32_t *data, uint32_t len)
{
    uint32_t baseAddr = 0U;
    uint32_t pages = 0U, i = 0U;
    uint32_t bytes = sizeof(uint32_t) * len;

    if(!sInitFlag) {
        /* Flash has not Init */
        return false;
    }

    /* Check alignment (Must be aligned to words) */
    if (bytes <= 0 || ((uint32_t) addr & 0x3) != 0 ) {
        /* Flash byte is empty */
        return false;
    }

    /* the base address of one page */
    baseAddr = addr - addr % FLASH_PAGE_SIZE;
    pages = (bytes - 1) / FLASH_PAGE_SIZE;
    for (i = 0; i <= pages; i++) {
        //Flash_SectorErase(baseAddr);
        baseAddr += FLASH_PAGE_SIZE;
    }

    for (i = 0; i < len; i++) {
        Flash_WriteWord(addr, data[i]);
        addr += 4;
    }

    return true;
}

bool BSP_FlashErase(uint32_t addr, uint32_t bytes)
{
    uint32_t baseAddr = 0U;
    uint32_t pages = 0U, i = 0U;

    if(!sInitFlag) {
        /* Flash has not Init */
#ifdef BOOTLOADER
        BSP_FlashInit();
#else
        return false;
#endif
    }

    /* Check alignment (Must be aligned to words) */
    if (bytes <= 0 || ((uint32_t) addr & 0x3) != 0 ) {
        /* Flash byte is empty */
        return false;
    }

    /* the base address of one page */
    baseAddr = addr - addr % FLASH_PAGE_SIZE;
    pages = (bytes + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;

    for (i = 0; i < pages; i++) {
        Flash_SectorErase(baseAddr);
        baseAddr += FLASH_PAGE_SIZE;
    }

    return true;
}

